package FlowGraph.Transformations;

import java.util.*;

import antlr.collections.AST;
import antlr.*;

import FlowGraph.*;
import FlowGraph.Nodes.*;
import JavaGrammar.*;
import SymbolTable.*;
import FlowGraph.StatementInfo.*;
import util.*;
import db.ClassData;

//////////////////////////////////////////////////////////////////////////
//// AnonymousClassExtraction
/**

@author Ivan Jeukens
@version v 0.1 12/11/2002
*/
public class AnonymousClassExtraction extends Transformation {

    public AnonymousClassExtraction(FlowGraph fg) {
        super(fg);
    }

    ///////////////////////////////////////////////////////////////////
    ////                        public  methods                    ////

    /* Para essa transformacao:
       arg0 = 
       
    */
    public void transform(AST n1, AST n2, AST n3, FlowGraphNode node,
            boolean bbSplit, int statementIndex, ClassData currentCInfo) {

        _extractAnonymousClass(n1, n2, n3, node, bbSplit, statementIndex,
            currentCInfo);
    }

    ///////////////////////////////////////////////////////////////////
    ////                        private methods                    ////

    private void _extractAnonymousClass(AST n1, AST n2, AST n3, FlowGraphNode node,
            boolean bbSplit, int statementIndex, ClassData currentCInfo) {

        String varname = new String("_anony" + _flowGraph.getUniqueCount());
        _flowGraph.incrementUniqueCount();

	LinkedAST top = _createLocalVarAST(varname, n2.getText());
 	STLocalVariableEntry entry = 
	    new STLocalVariableEntry(varname, STEntry.LOCAL, top, 0);
        entry.setType(Util.getType(n2.getText(), currentCInfo.getName(),
	    currentCInfo.getPackage(), currentCInfo.getImports()) );

        SymbolTable st = new SymbolTable();
	st.putElement(entry.getName(), entry);

        CommonToken tok;
	// Para o caso do Do, tenho que criar a vardef antes do loop
	if(node.getType() == FlowGraphNode.DO_CONDITION) {
            // No da definicao da variavel
	    BasicBlockNode bb = new BasicBlockNode(top);

            VarDefStatementInfo vardef = new VarDefStatementInfo(bb, top);
            bb.setStatementInfo(vardef, 0);
                            
	    DoConditionNode cond = (DoConditionNode) node;
	    FlowGraphNode n = cond.getContinueNode();

	    // addNodeBefore(bb, st, n,false);
            // No do methodcall

            tok = new CommonToken(JavaTokenTypes.EXPR, "EXPR");
            top = new LinkedAST(tok);
	}
	tok = new CommonToken(JavaTokenTypes.ASSIGN, "=");
        LinkedAST ast = new LinkedAST(tok);

	top.addChild(ast);
	ast.setParent(top);

	if(node.getType() == FlowGraphNode.DO_CONDITION) {
	    tok = new CommonToken(JavaTokenTypes.IDENT, varname);
	    LinkedAST vn = new LinkedAST(tok);
			    
	    ast.addChild(vn);
	    vn.setParent(ast);
	}

        LinkedAST expr;
        if(node.getType() != FlowGraphNode.DO_CONDITION) {
            tok = new CommonToken(JavaTokenTypes.EXPR, "EXPR");
            expr = new LinkedAST(tok);
        
            ast.addChild(expr);
	    expr.setParent(ast);
	}
	else {
	    expr = ast;
	}

	LinkedAST ob = Util.dupTree(n1);
	expr.addChild(ob);
	ob.setParent(expr);

	InnerClassNode icnode = new InnerClassNode(top, currentCInfo,
	    InnerClassNode.ANONYMOUS);
        if(node.getType() != FlowGraphNode.DO_CONDITION) {
	    icnode.setVarDef(true);
	}

	n1.setText(varname);
	n1.setType(JavaTokenTypes.IDENT);
	n1.setFirstChild(null);

        // Inclui o method call node no FG
        switch(node.getType()) {

            case FlowGraphNode.BASIC_BLOCK: {
                if(bbSplit) {
                    BreakBasicBlock transform = new BreakBasicBlock(_flowGraph);
                    LinkedList args = new LinkedList();
                    args.add(node);
                    args.add(new Integer(statementIndex));
                    transform.transform(args);
	        }
		_addNodeBefore(icnode, st, node, false);
	    } break;

            case FlowGraphNode.DO_CONDITION: {
                _addNodeBeforeDoCondition(icnode, node, true);
	    } break;

	    default: _addNodeBefore(icnode, st, node, true);
	}
    }

    ///////////////////////////////////////////////////////////////////
    ////                      private variables                    ////

}
